#include <gl/glew.h>
#include <QOpenGLContext>
#include <QOpenGLFunctions>
#include "EarthWrapper.h"
#include <osg/GraphicsContext>
#include <osgViewer/Viewer>
#include <osg/Camera>
#include <osgDB/ReadFile>
#include <osg/MatrixTransform>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthDrivers/gdal/GDALOptions>
#include <osgEarth/ImageLayer>
#include <osgEarth/Map>
#include <osgEarth/TerrainEngineNode>
#include <osgEarthDrivers/engine_mp/MPTerrainEngineNode>
#include <osg/Depth>
#include <osgViewer/Renderer>
#include <osg/LineWidth>
#include <osgEarthUtil/Sky>
//#include "SysConfig.h"

using namespace osgEarth;

EarthWrapper::EarthWrapper()
{
    _viewer = 0;
    _stereo_scale = 1.0;
    _stereo_mode = 0;
    _stereo_stage = 1;
    _ellipsoidModel = 0;
    _maploaded = 0;
}

void EarthWrapper::createMapNode(std::string path)
{
    //osg::Node* pnode = osgDB::readNodeFile("../user_data/config/earth.earth");
	osg::Node* pnode = osgDB::readNodeFile(path);

    //osg::Node* pnode = osgDB::readNodeFile("E:/hot/earth.earth");
    osgEarth::MapNode* mnode = dynamic_cast<osgEarth::MapNode*>(pnode);
	if (mnode){
		osgEarth::Map* map = mnode->getMap();
		this->_map = map;
		this->_mapNode = mnode;
		_maploaded = 1;
	}
}

void EarthWrapper::init(const EarthWrapperOptions &op)
{

    //_stereo_scale = SysConfig::intance()->stereo_scale;

    _rootNode = new osg::Group();

    _rootNode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);

    this->_viewer = op.viewer;
    _sceneNode = new osg::Group();
    _viewer->setSceneData(this->_rootNode);
	//_viewer->getDatabasePager()->setUpThreads(6, 3);
    _viewer->frame();
    this->_camera = _viewer->getCamera();
    
   // _camera->setLODScale(_camera->getLODScale() * 2.0f);
    // createWind();
}

void EarthWrapper::render(bool draw)
{
    if(!_viewer) return;

    if(this->_maploaded == 1){
        this->_maploaded = 2;

        _rootNode->addChild(this->_mapNode);
        _mapNode->addChild(_sceneNode);
        _ellipsoidModel = _mapNode->getMapSRS()->getEllipsoid();

//        osgEarth::Util::SkyNode *s_sky = osgEarth::Util::SkyNode::create(_mapNode);
//        s_sky->setMinimumAmbient(osg::Vec4f(0.6,0.6,0.6,0.6));
//        s_sky->setStarsVisible(true);
//        s_sky->setAtmosphereVisible(false);
//        _rootNode->addChild(s_sky);

        osgEarth::Util::EarthManipulator* pem = new osgEarth::Util::EarthManipulator();
        double xx,yy,zz;
        _map->getProfile()->getSRS()->getEllipsoid()->convertLatLongHeightToXYZ(
                    113,34,15000000,xx,yy,zz);
        osg::Matrix mat;
        mat.makeLookAt(osg::Vec3(xx,yy,zz),osg::Vec3(0,0,0),osg::Vec3(0,0,1));
        pem->setByInverseMatrix(mat);
        pem->setNode(_mapNode);
        pem->getSettings()->setThrowingEnabled(true);
        pem->getSettings()->bindMouseDoubleClick(
                    osgEarth::Util::EarthManipulator::ActionType::ACTION_NULL,1);
        _manipulator = pem;
        _viewer->setCameraManipulator(pem );
        _viewer->getDatabasePager()->setUpThreads(4,3);
        pem->home(0);

        osgEarth::Viewpoint vp( "Henan",113,33.6, 0, 0, -90, 10e6 );
        pem->setViewpoint(vp,5.0);
    }


    if(!draw){
        _viewer->advance();
        _viewer->eventTraversal();
        _viewer->updateTraversal();
        return;
    }

	if (_maploaded == 2) {
		osg::Vec3d u;
		_viewer->getCamera()->getViewMatrixAsLookAt(_eye, _center, u, 1000);

		double lat, lon, hei;
		if (_ellipsoidModel) {
			_ellipsoidModel->convertXYZToLatLongHeight(_eye.x(), _eye.y(), _eye.z(), lat, lon, hei);
		}

		//if (hei < 10000) {
		//	_viewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
		//	_viewer->getCamera()->setProjectionMatrixAsPerspective(50, __asp, 1, 10000000);
		//}
		//else {
		//	_viewer->getCamera()->setComputeNearFarMode(osg::Camera::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
		//}
	}

	osg::ref_ptr<osg::Camera> camera = _viewer->getCamera();
	camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glPopAttrib();
	
   // _camera->setDrawBuffer(GL_BACK);
    _viewer->frame();
    //_viewer->advance();
    //_viewer->eventTraversal();
    //_viewer->updateTraversal();

    //_viewer->renderingTraversals();
	glPushAttrib(GL_ALL_ATTRIB_BITS);
	
    
    //glClientActiveTexture(GL_TEXTURE0);
    //glActiveTexture(GL_TEXTURE0);
	//QOpenGLContext::currentContext()->functions()->glActiveTexture(GL_TEXTURE0);
 //   glEnable(GL_TEXTURE_2D);
 //   glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}

static EarthWrapper* g_ew = 0;
EarthWrapper *EarthWrapper::instance()
{
    if(g_ew == 0){
        g_ew = new EarthWrapper();
    }
    return g_ew;
    //static EarthWrapper ew;
    //return &ew;
}

void EarthWrapper::close()
{
    delete g_ew;
    g_ew = 0;
}

void EarthWrapper::setStereoMode(bool b){
    if(b){
        this->_stereo_mode = 6;
    }else{
        this->_stereo_mode = 0;
    }
}

void EarthWrapper::renderStereo(int lr)
{
    if(!_viewer) return;

    if(lr == 1){

        _viewer->advance();
        _viewer->eventTraversal();
        _viewer->updateTraversal();

        osg::Vec3d u;
        _viewer->getCamera()->getViewMatrixAsLookAt(_eye,_center,u,1000);
        double lat,lon,hei;
        if(_ellipsoidModel){
            _ellipsoidModel->convertXYZToLatLongHeight(_eye.x(),_eye.y(),_eye.z(),lat,lon,hei);
        }
        if(hei < 10000){
            _viewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
            _viewer->getCamera()->setProjectionMatrixAsPerspective(50,__asp,1,10000000);
        }else{
            _viewer->getCamera()->setComputeNearFarMode(osg::Camera::COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES);
        }

        _camera->setDrawBuffer(GL_BACK_LEFT);
        _camera->setReadBuffer(GL_BACK_LEFT);

        _viewer->renderingTraversals();

    }else{

        _camera->setDrawBuffer(GL_BACK_RIGHT);
        _camera->setReadBuffer(GL_BACK_RIGHT);

        double lat,lon,hei;
        _ellipsoidModel->convertXYZToLatLongHeight(_eye.x(),_eye.y(),_eye.z(),lat,lon,hei);

        osg::Matrix m1 = _camera->getViewMatrix();
        osg::Matrix m2;
        osg::Vec3d e2,c2,u2;
        double dis = hei;
        m1.getLookAt(e2,c2,u2,dis*10);
        osg::Vec3d off = (c2 - e2) ^ u2;
        off.normalize();
        off = off * _stereo_scale * dis / 60.0;
        e2 = e2 + off;
       // c2 = c2 + off;
        m2.makeLookAt(e2,c2,u2);
        this->_camera->setViewMatrix(m2);
        _viewer->renderingTraversals();
        this->_camera->setViewMatrix(m1);
    }
    glPushAttrib(GL_ALL_ATTRIB_BITS);
    glClientActiveTexture(GL_TEXTURE0);
    //glActiveTexture(GL_TEXTURE0);
    glEnable(GL_TEXTURE_2D);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
}





